import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JPanel;

/**
 * 
 */

/**
 * @author Joe
 * 
 */
public class GameData extends JPanel
	implements MouseListener, MouseMotionListener, Runnable
	{
	/*
	 * Game States
	 */
	static final int NO_ACTION = 0;
	static final int GAME_START = 1;
	static final int GAME_END = 2;
	static final int ROUND_START = 3;
	static final int ROUND_END = 4;
	static final int SCORE_TURN = 5;
	static final int PLAYER_TURN = 6;
	static final int CHANGE_PLAYER = 7;
	static final int BUTTON_LOC_X = 0;
	static final int BUTTON_LOC_Y = 725;
	
	// Constants
	final int UI_ELEMENTS = 2;
	final int TWO_PLAYERS = 2;

	/*
	 * These are the string constants
	 */
	final String gPlayerText = "Player ";
	final String gRoundText = "Round: ";
	final String gTurnText = "Turn: ";
	final String rdText = "Roll Dice";
	final String npText = "Next Player";
	
	/*
	 * rect for the buttons
	 * 0 = roll dice
	 * 1 = next player
	 */
	uiElements[] uiButtons;

	// mouse position
	Coordinates mPos;
	// screen size
	Coordinates screenDim;
	Player[] player;
	// number of players
	final static int MAX_PLAYERS = 6;
	final static int MAX_REROLL = 3;

	// Class member variables
	// current Player
	int currentPlayer;
	// current player turn
	int turnRound;
	// current turn of the round
	int gameRound;
	// running
	boolean running;
	// no free dice
	boolean noFreeDice;
	// no roll
	boolean noRoll;
	// first run
	boolean firstRun;
	// text height
	int text_h;

	// current functions active
	int gameState;
	
	// Buttons
	// New Game
	Button ngButton;
	// Roll Dice
	Button rdButton;
	// Next Player
	Button npButton;
	
	// button images
	Image rdImage;
	Image npImage;

	// initialize for all above functions
	GameData(int a_x, int a_y) {
		// initialize
		player = new Player[TWO_PLAYERS];
		uiButtons = new uiElements[UI_ELEMENTS];
		mPos = new Coordinates();
		screenDim = new Coordinates();
		noFreeDice = false;
		noRoll = false;
		firstRun = true;
		text_h = 0;
		
		currentPlayer = 0;
		gameRound = 0;
		turnRound = 0;
		gameState = ROUND_START;
		
		// initialize player
		for (int i = 0; i < player.length; i++) {
			player[i] = new Player();
		}
		
		// set screen size
		screenDim.setX(a_x);
		screenDim.setY(a_y);
		
		//initialize New Game Button
		//initialize Roll Dice Button
		System.out.println("x: " + BUTTON_LOC_X + " | y:" + screenDim.getY()/2);
		uiButtons[0] = new uiElements("rdButton.png", BUTTON_LOC_X, screenDim.getY()/2,80,64);
		//initialize Next Player Button
		System.out.println("x: " + (BUTTON_LOC_X + screenDim.getX()/8) + " | y:" + screenDim.getY()/2);
		uiButtons[1] = new uiElements("npButton.png", BUTTON_LOC_X + screenDim.getX()/8, screenDim.getY()/2,128,64);

		// starts mouse watch
		addMouseListener(this);
		addMouseMotionListener(this);
	}

	// font's for all the color in the draw
	Font f = new Font("Whiskey Bravo Victor", Font.BOLD | Font.ITALIC, 30);
	FontMetrics fm;
	public void paintComponent(Graphics g) {
		if (firstRun) {
			fm = g.getFontMetrics();
			text_h = (int) fm.getLineMetrics(rdText, g).getHeight()*2;
			for (int i = 0; i < player.length; i++) {
				player[i].sb.setText_height(fm.getHeight());
			}			
			firstRun = false;
		}
		
		g.clearRect(0, 0, screenDim.getX(), screenDim.getY());
		player[currentPlayer].draw(g);
		g.setFont(f);
		g.setColor(Color.BLACK);
		g.drawString(gPlayerText.concat(String.valueOf(currentPlayer)), 0, text_h);
		g.drawString(gRoundText.concat(String.valueOf(gameRound)), 0, screenDim.getY() - (int)(1.5 * text_h));
		g.drawString(gTurnText.concat(String.valueOf(turnRound)), screenDim.getX()/2, screenDim.getY() - (int)(1.5 * text_h));
		
		for (int i = 0; i < uiButtons.length; i++) {
			uiButtons[i].draw(g);
		}
	}

	// update game logic and information
	void update() {
		// performs operations according to state
//		System.out.println("gameState: " + gameState);
		switch (gameState) {
		case NO_ACTION:
			break;
		case GAME_END: // ends the program
			running = false;
			break;
		case ROUND_START: // starts a new game
			break;
		case ROUND_END: // ends the current game, displays winner.
			break;
		case CHANGE_PLAYER:
			// reset turn
			gameState = NO_ACTION;
			// 0 == PLAYER_IDLE
			player[currentPlayer].setGameState(0);
			turnRound = 0;
			gameRound++;
			player[currentPlayer].unFreezeAll();
			noRoll = false;

			if (currentPlayer != (2 - 1)) {
				currentPlayer++;
			} else {
				currentPlayer = 0;
			}
			// refresh dice after scoring
			player[currentPlayer].diceRollAll();
			gameState = NO_ACTION;
			break;
		case PLAYER_TURN:
			if (player[currentPlayer].allFrozen()) {
				noRoll = true;
			} else if (turnRound == MAX_REROLL) {
				noRoll = true;
				// 0 == PLAYER_IDLE
				player[currentPlayer].setGameState(0);
			} else {
				player[currentPlayer].update(mPos, screenDim);
				turnRound++;
				gameState = NO_ACTION;
				// 0 == PLAYER_IDLE
				player[currentPlayer].setGameState(0);
			}
			break;
		case SCORE_TURN:
			if (player[currentPlayer].allScored()) {
				gameState = ROUND_END;
			} else {
				 player[currentPlayer].update(mPos, screenDim);
				// 0 == PLAYER_IDLE
				player[currentPlayer].setGameState(0);
				gameState = NO_ACTION;
				break;
			}
		}
//		player[currentPlayer].update(mPos, screenDim);
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		for (int i = 0; i < 5; i++) {
			if (e.getX() > player[currentPlayer].getDicePosX(i) && e.getX() < (player[currentPlayer].getDicePosX(i) + player[currentPlayer].getDiceDim(i)) &&
				e.getY() > player[currentPlayer].getDicePosY(i) && e.getY() < (player[currentPlayer].getDicePosY(i) + player[currentPlayer].getDiceDim(i))) {
				player[currentPlayer].freezeDiceValue(i);
			}
		}
		repaint();
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mousePressed(MouseEvent e) {
//		System.out.println("x: " + e.getX() + " | y: " + e.getY());
		if(noRoll || turnRound != 0)
		{
			if((e.getX() > screenDim.getX()/2 && e.getX() < screenDim.getX()) &&
					(e.getY() > 0 && e.getY() < screenDim.getY()))
			{
				player[currentPlayer].setGameState(2);
				gameState = SCORE_TURN;
			}
		}
		for (int i = 0; i < uiButtons.length; i++) {
			if (uiButtons[i].isInBounds(e.getX(), e.getY())) {
				switch (i) {
				case 0:
					player[currentPlayer].setGameState(1);
					gameState = PLAYER_TURN;
					break;
				case 1:
					gameState = CHANGE_PLAYER;
					break;
				default:
					break;
				}
			}
		}
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseDragged(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseMoved(MouseEvent e) {
		mPos.setX(e.getX());
		mPos.setY(e.getY());
	}

	// has player exceeded maximum rolls allowed?
	boolean canRoll() {
		return noRoll;
	}
	
	boolean gameIsRunning = true;
	public void run()
	{
		while(gameIsRunning)
		{
			//update
			update();
			//draw
			repaint();
			try {
				Thread.sleep(1000);
			} catch (Exception e) {
			}
		}
	}
}
